<!DOCTYPE html>
<html lang="en">
<head>
    <title>TikTokWeb</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="referrer" content="never">
    <meta name="description" content="download douyin video images without water mask">
    <meta name="robots" content="noindex, nofollow">
    <link rel="stylesheet" href="../static/stylesheets/milligram.min.css">
    <link rel="stylesheet" href="../static/stylesheets/progress.css">
    <link rel='stylesheet' href='../static/stylesheets/unicons.css'>
    <link rel='stylesheet' href='../static/stylesheets/style.css'>
    <link rel="stylesheet" href="../static/stylesheets/sweetalert2.min.css">
    <link rel="shortcut icon" href="../static/images/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon" href="../static/images/favicon.ico">
    <script src="../static/javascripts/jquery.min.js"></script>
    <script src="../static/javascripts/jquery.cookie.min.js"></script>
    <script src="../static/javascripts/jszip.min.js"></script>
    <script src="../static/javascripts/FileSaver.min.js"></script>
    <script src="../static/javascripts/sweetalert2.min.js"></script>
    <script src="../static/javascripts/img2zip.js"></script>
    <script src="../static/javascripts/progress.js"></script>
</head>
<body class="bs-docs-home">
<div class="col-md-8">
    <div class="tk">
        <h1>TikTokWeb</h1>

        <blockquote>
            <p><em>先填写你的抖音cookie，然后输入长短链点击解析试试吧🎉！</em></p>
        </blockquote>

        <div class="input-group input-group-lg" style="margin-bottom: 10px;">
            <input type="text" class="form-control link-input" name="vurl" value="https://v.douyin.com/NKyY6Ch/" placeholder="请输入作品链接" id="video_url">
            <div class="input-group-btn">
                <div class="btn-clear" id="btn-clear">
                    <button class="btn btn-default" type="button" value="清空并读取剪贴板内容" onclick="clearAndPaste()">清空并读取剪贴板内容</button>
                    <button class="btn btn-default" type="button" value="解析" id="get">解析</button>
                    <button class="button button-clear" type="submit" value="设置Cookie" id="setcookie">设置Cookie</button>
                </div>
            </div>
            <div class="input-group-btn">
                <!-- cookie配置-->
                <form style="display: none;" id="cookieform">
                    <fieldset>
                        <ul>
                            <li>
                                只需填写cookie的value，不需要填写key 😀
                            </li>
                            <li>
                                大部分情况下只填写ttwid即可解析 😉
                            </li>
                            <li>
                                例如 ttwid的值是1%7CxvIZqo2hPx…………只需要填这部分即可 🥴
                            </li>
                            <li>
                                你的所有信息均储存在本地 🚨
                            </li>
                        </ul>
                        <pre class="savesuccess" style="display: none;"><code>保存成功</code></pre>
                        <pre class="saveerror" style="display: none;"><code>保存失败</code></pre>
                        <label for="odin_tt_Field">odin_tt</label>
                        <input type="text" placeholder="odin_tt的值" id="odin_tt_Field">
                        <label for="passport_csrf_token_Field">passport_csrf_token</label>
                        <input type="text" placeholder="passport_csrf_token的值" id="passport_csrf_token_Field">
                        <label for="sessionid_ss_Field">sessionid_ss</label>
                        <input type="text" placeholder="sessionid_ss的值" id="sessionid_ss_Field">
                        <label for="ttwid_Field">ttwid</label>
                        <input type="text" placeholder="ttwid的值" id="ttwid_Field">
                        <label for="msToken_Field">msToken</label>
                        <input type="text" placeholder="msToken的值" id="msToken_Field">
                        <button class="btn btn-default" type="button" value="保存" id="savecookie">保存</button>
                        <button class="btn btn-default" type="button" value="清理" id="cleancookie">清理</button>
                    </fieldset>
                </form>
            </div>
        </div>
    </div>
</div>

<script>
    function clearAndPaste() {
        // 清空输入框内容
        document.getElementById('video_url').value = '';

        // 读取剪贴板内容并赋值给输入框
        navigator.clipboard.readText().then(function(clipText) {
            document.getElementById('video_url').value = clipText;
        }).catch(function(err) {
            console.error('Failed to read clipboard contents: ', err);
        });
    }
</script>


        <!-- 作品详细-->
        <div style="display: none;" id="video_info">
            <div class="card">
                <div class="card-body">
                    <table style="overflow: auto;">
                        <tr align="center">
                            <td>
                                <% if (videoData.type=='图集'){%>
                                    <div class="images_play">
                                        <% for (var i = 0;i < videoData.images.length;i++) { %>
                                            <img alt="<%- videoData.desc %>"crossorigin="anonymous" src="<%- videoData.images[i] %>">
                                        <%}%>
                                    </div>
                                <%} else {%>
                                    <div class="video_play">
                                        <video autoplay width="50%" controls="controls" id="play" preload="auto" type="video/mp4" webkit-playsinline="true" playsinline="" x5-video-player-type="h5" x5-video-player-fullscreen="portraint">
                                            <source src="<%= videoData.url %>" type="video/mp4">
                                        </video>
                                    </div>
                                <%}%>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <div class="row">
                                    <table align="center" style="width: 60%">
                                        <tr align="right">
                                            <td style="width: 40%"><span class="column">类型</span></td>
                                            <td><span class="column" id="type" style="text-align: center;display: block;"><%= videoData.type %></span></td>
                                        </tr>
                                        <tr align="right">
                                            <td style="width: 40%"><span class="column">文案</span></td>
                                            <td><span class="column" id="desc" style="text-align: center;display: block;"><%= videoData.desc %></span></td>
                                        </tr>
                                        <tr align="right">
                                            <td style="width: 40%"><span class="column">抖音ID</span></td>
                                            <td><span class="column" id="unique_id" style="text-align: center;display: block;"><%= videoData.unique_id %></span></td>
                                        </tr>
                                        <tr align="right">
                                            <td style="width: 40%"><span class="column">视频ID</span></td>
                                            <td><span class="column" id="video_id" style="text-align: center;display: block;"><%= videoData.video_id %></span></td>
                                        </tr>
                                        <tr align="right">
                                            <td style="width: 40%"><span class="column">主页</span></td>
                                            <td><a class="column" id="userhome" target="_blank" href="<%= videoData.userhome %>" style="text-align: center;display: block;"><%= videoData.nickname %></a></td>
                                        </tr>
                                    </table>
                                </div>
                            </td>
                        </tr>
                        <tr align="center">
                            <td align="center">
                                <% if (videoData.type=='图集'){%>
                                    <a id="downloadIMG" class="button" role="button" href="javascript:void(0);" rel="noreferrer">下载所有</a>
                                <%} else { %>
                                    <a id="downloadVIDEO" class="button" role="button" href="#" download="<%= videoData.desc %>.mp4" rel="noreferrer">下载视频</a>
                                <% }%>
                                <a id="downloadMUSIC" class="button" role="button" href="#" download="<%= videoData.m_title %>.mp3" rel="noreferrer">
                                    <% if(videoData.music=='') {%>该原声不可用<%} else {%>下载原声<%} %>
                                </a>
                            </td>
                        </tr>
                    </table>
                </div>
            </div>
        </div>

        <!-- 页脚-->
        <footer>
            <span style="text-align: center; display: block; padding: 20px;">
                <a target="_blank" style="color: #9b4dca;" rel="noreferrer" href="https://github.com/Johnserf-Seed/TikTokWeb">GitHub · JohnserfSeed · 2023</a>
            </span>
        </footer>

        <!-- 回到顶部-->
        <div class="progress-wrap">
            <svg class="progress-circle svg-content" width="100%" height="100%" viewBox="-1 -1 102 102">
                <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"/>
            </svg>
        </div>
    </div>
</div>
<script>
    const Toast = Swal.mixin({
        toast: true,
        position: 'top-end',
        showConfirmButton: false,
        timer: 3000,
        timerProgressBar: true,
        didOpen: (toast) => {
            toast.addEventListener('mouseenter', Swal.stopTimer)
            toast.addEventListener('mouseleave', Swal.resumeTimer)
        }
    });
    $(document).ready(function(){
        const COOKIE_FORM = '#cookieform';
        const VIDEO_INFO = '#video_info';
        const VIDEO_URL = "#video_url";
        const COOKIE_NAME = 'dycookie';
        const FIELDS_MAP = {
            'odin_tt': '#odin_tt_Field',
            'passport_csrf_token': '#passport_csrf_token_Field',
            'sessionid_ss': '#sessionid_ss_Field',
            'ttwid': '#ttwid_Field',
            'msToken': '#msToken_Field'
        };
        const URL_REGEXP = /((http|https):\/\/([\w\-]+\.)+[\w\-]+(\/[\w\u4e00-\u9fa5\-\.\/?\@\%\!\&=\+\~\:\#\;\,]*)?)/ig;

        function toggleForm() {
            $(COOKIE_FORM).toggle();
        }

        function populateFields(dycookie) {
            for (let key in FIELDS_MAP) {
                if (dycookie[key]) {
                    $(FIELDS_MAP[key]).val(dycookie[key]);
                }
            }
        }

        function showToast(message, icon) {
            Toast.fire(message, '', icon);
            $('#cookieform').hide();
        }

        function updateVideoLink() {
            try {
                let query = window.location.href.split("=")[1];
                query = decodeURI(query);

                if (query === 'undefined') {
                    $(VIDEO_INFO).hide();
                } else {
                    $(VIDEO_URL).val(query);
                    $(VIDEO_INFO).show();
                }
                if ('<%- videoData.work %>' === 'false') {
                    $(VIDEO_INFO).hide();
                    Swal.fire('警告','抖音的cooki无效，请重新填写','warning');
                }
            } catch (error) {
                console.error("Error:", error);
            }
        }

        $('#setcookie').click(toggleForm);
        updateVideoLink();

        $("#savecookie").click(function() {
            const dycookie = {};

            for (let key in FIELDS_MAP) {
                dycookie[key] = $(FIELDS_MAP[key]).val();
            }

            try {
                $.cookie(COOKIE_NAME, JSON.stringify(dycookie), { expires: 30 });
                showToast('保存成功', 'success');
            } catch {
                showToast('保存失败', 'error');
            }
        });

        $("#cleancookie").click(function() {
            try {
                $.removeCookie(COOKIE_NAME, { path: '/' });
                for (let key in FIELDS_MAP) {
                    $(FIELDS_MAP[key]).val('');
                }
                showToast('清理成功', 'success');
            } catch (error) {
                showToast('清理失败', 'error');
                console.log(error);
            }
        });

        if (!$.cookie(COOKIE_NAME)) {
            Swal.fire('提示', '填写抖音的cookie才可以正常解析', 'warning');
        } else {
            const dycookie = JSON.parse($.cookie(COOKIE_NAME));
            populateFields(dycookie);
        }

        $("#downloadIMG").click(event => {
            event.preventDefault();
            Toast.fire('图集正在打包中，请稍等...','','info')
            downloadAll('<%- videoData.images %>','<%- videoData.desc %>')
        });

        $("#downloadVIDEO").click(event => {
            event.preventDefault();
            Toast.fire('视频正在下载中，请稍等...', '', 'info');
            downloadFile('<%- videoData.url %>', '<%= videoData.desc %>.mp4');
        });

        $("#downloadMUSIC").click(event => {
            event.preventDefault();
            Toast.fire('音乐正在下载中，请稍等...', '', 'info');
            downloadFile('<%= videoData.music %>', '<%= videoData.m_title %>.mp3');
        });

        $("#get").click(function() {
            if (!$.cookie('dycookie')) {
                Swal.fire('警告','请先填写抖音的cookie才可以正常解析作品','warning');
                return;
            }

            let video_url = $('#video_url').val().trim();

            if (!video_url) {
                Swal.fire('警告','还没有输入链接哦','warning');
                return;
            }

            if (!URL_REGEXP.test(video_url)) {
                Swal.fire('错误','请填写正确作品链接','error');
                return;
            }

            window.location.href = "/api?url=" + video_url.match(URL_REGEXP)[0];
        });
    });
</script>
<script src="../static/javascripts/downloadFile.js"></script>
</body>
</html>
